﻿using FuiouCode;
using FuiouMerchantAccess.Models.Request;
using FuiouMerchantAccess.Models.Response;
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;

namespace FuiouMerchantAccess {
    public class MerchantAccess {
        readonly Config config;

        public MerchantAccess() {
            config = new Config();
        }

        public MerchantAccess(Config _config) {
            if (_config == null) {
                config = new Config();
            } else {
                config = _config;
            }
        }

        /// <summary>
        /// 商户信息更新
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public WxMchntEditResponseInfo WxMchntEdit(WxMchntEditRequestInfo request) {
            if (string.IsNullOrEmpty(request.TraceNo)) {
                throw new FuiouException("流水号不能为空");
            }

            if (string.IsNullOrEmpty(request.FyMchntCd)) {
                throw new FuiouException("富友商户代码不能为空");
            }

            Dictionary<string, object> pairs = Utils.ObjectToMap(request);

            if (!pairs.IsSet("ins_cd")) {
                pairs.SetValue("ins_cd", config.InsCd);
            }

            WxMchntEditResponseInfo response = Run<WxMchntEditResponseInfo>(pairs, config.Url, "XML", "wxMchntUpd", false);

            return response;
        }

        /// <summary>
        /// 商户名称判重
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public WxMchntResponseInfo WxMchntNameCheck(WxMchntNameCheckRequestInfo request) {
            if (string.IsNullOrEmpty(request.TraceNo)) {
                throw new FuiouException("流水号不能为空");
            }

            if (string.IsNullOrEmpty(request.MchntName)) {
                throw new FuiouException("商户名称不能为空");
            }

            Dictionary<string, object> pairs = Utils.ObjectToMap(request);

            if (!pairs.IsSet("ins_cd")) {
                pairs.SetValue("ins_cd", config.InsCd);
            }

            WxMchntResponseInfo response = Run<WxMchntResponseInfo>(pairs, config.Url, "XML", "wxMchntNameCheck", false);

            return response;
        }

        /// <summary>
        /// 商户渠道子商户号查询
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public ChnlSubMchIdQueryResponseInfo ChnlSubMchIdQuery(ChnlSubMchIdQueryRequestInfo request) {
            if (string.IsNullOrEmpty(request.TraceNo)) {
                throw new FuiouException("流水号不能为空");
            }

            if (string.IsNullOrEmpty(request.MchntCd)) {
                throw new FuiouException("申请商户号不能为空");
            }

            if (string.IsNullOrEmpty(request.MchntTp)) {
                throw new FuiouException("商户类型不能为空");
            }

            Dictionary<string, object> pairs = Utils.ObjectToMap(request);

            if (!pairs.IsSet("ins_cd")) {
                pairs.SetValue("ins_cd", config.InsCd);
            }

            ChnlSubMchIdQueryResponseInfo response = Run<ChnlSubMchIdQueryResponseInfo>(pairs, config.Url, "XML", "chnlSubMchIdQuery", false);

            return response;
        }

        private T Run<T>(Dictionary<string, object> map, string url, string format, string actionName, bool isCheckSign = true) where T : class {
            StringBuilder result = new StringBuilder("");
            HttpUtils httpUtils = new HttpUtils();
            Encoding encoding;
            string reqBody;

            if (format.Equals("XML")) {
                Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

                encoding = Encoding.GetEncoding(config.Charset);

                reqBody = "<?xml version=\"1.0\" encoding=\"" + config.Charset + "\" standalone=\"yes\"?>" + map.MapToXml(config.Key, config.Charset, "MD5");

                Console.WriteLine("==============================待编码字符串==============================\r\n" + reqBody);

                reqBody = Utils.UrlEncode(reqBody, encoding);

                Console.WriteLine("==============================编码后字符串==============================\r\n" + reqBody);

            } else {
                encoding = Encoding.UTF8;

                string sign = Utils.GetSign(map, config.Key, config.Charset, "MD5", format);

                if (!map.IsSet("sign")) {
                    map.SetValue("sign", sign);
                }

                reqBody = Newtonsoft.Json.JsonConvert.SerializeObject(map);
            }

            Dictionary<string, object> nvs = new Dictionary<string, object> {
                { "action", actionName },
                { "req", reqBody}
            };

            httpUtils.Post(url, nvs, result, config.Charset);

            string strResult = HttpUtility.UrlDecode(result.ToString(), encoding);
            if (isCheckSign) {
                if (!Utils.CheckSign(strResult, config.Key, config.Charset, "MD5", format)) {
                    throw new FuiouException("返回数据异常，或验签失败");
                }
            }

            if (format.Equals("XML")) {
                return Utils.XmlDeserialize<T>(strResult, config.Charset);
            } else {
                return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(strResult);
            }
        }
    }
}
